function base_learner = FLD_training(Xc,Xs,i,base_learner,OOB,subspace,settings,sigCstored,sigSstored)
% FLD TRAINING
if settings.bootstrap
    Xm = Xc(OOB.SUB,subspace);
    Xp = Xs(OOB.SUB,subspace);
else
    Xm = Xc(:,subspace);
    Xp = Xs(:,subspace);
end

% remove constants
remove = false(1,size(Xm,2));
adepts = unique([find(Xm(1,:)==Xm(2,:)) find(Xp(1,:)==Xp(2,:))]);
for ad_id = adepts
    U1=unique(Xm(:,ad_id));
    if numel(U1)==1
        U2=unique(Xp(:,ad_id));
        if (numel(U2)==1) && (U1==U2)
            remove(ad_id) = true; 
        end
    end
end
clear adepts ad_id

muC  = sum(Xm,1); muC = double(muC)/size(Xm,1);
muS  = sum(Xp,1); muS = double(muS)/size(Xp,1);
mu = (muS-muC)';

% calculate sigC
xc = get_xc(Xm,muC);
if length(sigCstored.k)<i, sigCstored.k(end+1:end+10) = 0; end
K = sigCstored.k(i);
if K>0 && ~strcmp(settings.keep_cov,'no')
    if K<settings.k
        xc1 = xc(:,1:K);
        xc2 = xc(:,K+1:end);
        sigC = zeros(size(xc,2),'single');
        if strcmp(settings.keep_cov,'harddrive')
            TMP = load(sigCstored.sig{i});
            sigC(1:K,1:K) = TMP.sig; clear TMP
        end
        if strcmp(settings.keep_cov,'memory')
            sigC(1:K,1:K) = sigCstored.sig{i};
        end
        sigC(1:K,K+1:end) = xc1'*xc2;
        sigC(K+1:end,1:K) = sigC(1:K,K+1:end)';
        sigC(K+1:end,K+1:end) = xc2'*xc2;
    else
        %Decrease dim of cached covariance
        sigC = sigCstored.sig{i}(1:settings.k,1:settings.k);
    end
else
    sigC = xc'*xc;
end
% save sigC
if sigCstored.k(i)<settings.k && ~strcmp(settings.keep_cov,'no')
    sigCstored.k(i) = settings.k;
    if isempty(sigCstored.sig{i})
        sigCstored.sig{i} = generateUniqueTmpName();
    end
    if strcmp(settings.keep_cov,'harddrive')
        save(sigCstored.sig{i},'sigC');
    end
    if strcmp(settings.keep_cov,'memory')
        sigCstored.sig{i} = sigC;
    end
end

% calculate sigS
clear xc xc1 xc2
xc = get_xc(Xp,muS);
if length(sigSstored.k)<i, sigSstored.k(end+1:end+10) = 0; end
K = sigSstored.k(i);
if K>0 && ~strcmp(settings.keep_cov,'no')
    if K<settings.k
        xc1 = xc(:,1:K);
        xc2 = xc(:,K+1:end);
        sigS = zeros(size(xc,2),'single');
        if strcmp(settings.keep_cov,'harddrive')
            TMP = load(sigSstored.sig{i});
            sigS(1:K,1:K) = TMP.sig; clear TMP
        end
        if strcmp(settings.keep_cov,'memory')
            sigS(1:K,1:K) = sigSstored.sig{i};
        end
        sigS(1:K,K+1:end) = xc1'*xc2;
        sigS(K+1:end,1:K) = sigS(1:K,K+1:end)';
        sigS(K+1:end,K+1:end) = xc2'*xc2;
    else
        %decrease dim of cached covariance
        sigS = sigSstored.sig{i}(1:settings.k,1:settings.k);

    end
else
    sigS = xc'*xc;
end
% save sigS
if sigSstored.k(i)<settings.k && ~strcmp(settings.keep_cov,'no')
    sigSstored.k(i) = settings.k;
    if isempty(sigSstored.sig{i})
        sigSstored.sig{i} = generateUniqueTmpName();
    end
    if strcmp(settings.keep_cov,'harddrive')
        save(sigSstored.sig{i},'sigS');
    end
    if strcmp(settings.keep_cov,'memory')
        sigSstored.sig{i} = sigS;
    end
end

sigC = double(sigC)/size(Xm,1);
sigS = double(sigS)/size(Xp,1);

sigCS = sigC + sigS;

% regularization
sigCS = sigCS + 1e-10*eye(size(sigC,1));

% check for NaN values (may occur when the feature value is constant over images)
clear nan_values
nan_values = sum(isnan(sigCS))>0;
nan_values = nan_values | remove;

sigCS = sigCS(~nan_values,~nan_values);
mu = mu(~nan_values);
lastwarn('');
warning('off','MATLAB:nearlySingularMatrix');
warning('off','MATLAB:singularMatrix');

base_learner.w = sigCS\mu;

% regularization (if necessary)
[txt,warnid] = lastwarn();
while strcmp(warnid,'MATLAB:singularMatrix') || (strcmp(warnid,'MATLAB:nearlySingularMatrix') && ~settings.ignore_warnings)
    lastwarn('');
    if ~exist('counter','var'), counter=1; else counter = counter*5; end
    sigCS = sigCS + counter*eps*eye(size(sigCS,1));
    base_learner.w = sigCS\mu;
    [txt,warnid] = lastwarn();
end    
warning('on','MATLAB:nearlySingularMatrix');
warning('on','MATLAB:singularMatrix');
if length(sigCS)~=length(sigC)
    % resolve previously found NaN values, set the corresponding elements of w equal to zero
    w_new = zeros(length(sigC),1);
    w_new(~nan_values) = base_learner.w;
    base_learner.w = w_new;
end

% find threshold to minimize FA+MD
[base_learner] = findThreshold(Xm,Xp,base_learner);
